<?php
/**
 * @Author: king
 * @Date:   2019-01-14 21:13:41
 * @Last Modified by:   king
 * @Last Modified time: 2019-04-04 20:52:36
 */
namespace App\Models\Api;


use App\Tools\Astrolog\Astrolog;
use App\Tools\Astrolog\AuthenticateLove;
use App\Tools\Astrolog\Synastry;
use App\Models\Api\MessageCenter;
use App\Models\Api\Base;
use App\Exceptions\ApiException;
use think\Cache;

/**
 * 鉴爱
 * Class Authenticate
 * @package App\Models\Api\Base
 */
class Authenticate extends Base
{
    protected $table = 'authenticate';

    /**
     * 缓存时间 7天
     * 86400为一天
     */
    const CACHE_TIME = 86400 * 7;
    /**
     * 鉴爱结果是否实时计算
     */
    private $resultAlwaysCalculate = false;

    protected $recodeModel;
    protected $wechatRecodeModel;
    protected $authenticateTextModel;

    /**
     * 获取当前用户的鉴爱历史记录
     * @param array $map
     * @return array
     * @throws \app\common\lib\exception\ApiException
     */
    public function getAuthenticateHistory($map = [])
    {
        $uid = $map['uid'];

        $where = ['uid' => $uid, 'status' => 0];

        $history = false;

        //获取缓存的鉴爱历史记录
        if ($this->cache_on >= 1 && Cache::has('authenticate_history_' . $uid)) {
            $history = Cache::get('authenticate_history_' . $uid);
        }

        //从数据库获取鉴爱历史记录并缓存
        if ($history === false) {
            try {
                $history = $this->select('rid1','wid1','rid2','wid2','result1','result2')->where($where)->orderBy('create_time', 'DESC')->get();

                $history = json_decode(json_encode($history, true), true);
                if ($this->cache_on >= 1) {
                    Cache::set('authenticate_history_' . $uid, $history, self::CACHE_TIME);
                }
            } catch (\Exception $e) {
                $history = [];
            }
        }

        // 变量初始化
        $data = $arr = $recc = [];

        //重组鉴爱历史记录
        foreach ($history as $dd) {
            $rid1 = $dd['rid1'];
            $wid1 = $dd['wid1'];
            $rid2 = $dd['rid2'];
            $wid2 = $dd['wid2'];

            $Recode = new Recode();
            $WechatRecode = new WechatRecode();

            if ($rid1 && $rid2) {
                //获取鉴爱的结果id
                $data['result1'] = $dd['result1'];
                //获取鉴爱的档案信息
                $recode1 = $Recode->getRecodeWithAstro(['id' => $rid1]);
                $recode2 = $Recode->getRecodeWithAstro(['id' => $rid2]);

                if ($recode1 && $recode2) {
                    //将档案1日月升转换为文字
                    $sun1 = $this->recode_astro($recode1['sun']);
                    $moon1 = $this->recode_astro($recode1['moon']);
                    $asc1 = $this->recode_astro($recode1['asc']);
                    //将档案2日月升转换为文字
                    $sun2 = $this->recode_astro($recode2['sun']);
                    $moon2 = $this->recode_astro($recode2['moon']);
                    $asc2 = $this->recode_astro($recode2['asc']);

                    $arr = [
                        'rid1' => $rid1,
                        'rid2' => $rid2,
                        'isself1' => false,
                        'isself2' => false,
                        'sun_moon_asc1' => '日' . $sun1 . '月' . $moon1 . '升' . $asc1,
                        'sun_moon_asc2' => '日' . $sun2 . '月' . $moon2 . '升' . $asc2,
                        'name1' => $recode1['name'],
                        'name2' => $recode2['name'],
                        'avatar1' => $recode1['avatar'],
                        'avatar2' => $recode2['avatar']
                    ];
                    if ($recode1['isself'] == 1) {
                        $arr['isself1'] = true;
                    }
                    if ($recode2['isself'] == 1) {
                        $arr['isself2'] = true;
                    }
                }

            } elseif (($rid1 && $wid2) || ($wid1 && $rid2)) {

                $rid = $rid1 ? $rid1 : $rid2;
                $wid = $wid1 ? $wid1 : $wid2;

                //获取鉴爱的结果id
                $data['result1'] = $dd['result1'];
                if ($rid1 && $wid2) {
                    //获取鉴爱的档案信息
                    $recode1 = $Recode->getRecodeWithAstro(['id' => $rid]);

                    $recode2 = $WechatRecode->getWechatRecode(['wid' => $wid, 'uid' => $uid]);

                    if ($recode1 && $recode2) {
                        //将档案1日月升转换为文字
                        $sun1 = $this->recode_astro($recode1['sun']);
                        $moon1 = $this->recode_astro($recode1['moon']);
                        $asc1 = $this->recode_astro($recode1['asc']);

                        $arr = [
                            'rid1' => $rid,
                            'wid2' => $wid,
                            'isself1' => false,
                            'isself2' => false,
                            'sun_moon_asc1' => '日' . $sun1 . '月' . $moon1 . '升' . $asc1,
                            'sun_moon_asc2' => $recode2['sun_moon_asc'],
                            'name1' => $recode1['name'],
                            'name2' => $recode2['name'],
                            'avatar1' => $recode1['avatar'],
                            'avatar2' => $recode2['avatar']
                        ];
                        if ($recode1['isself'] == 1) {
                            $arr['isself1'] = true;
                        }
                    }

                } elseif ($wid1 && $rid2) {
                    //获取鉴爱的档案信息
                    $recode1 = $WechatRecode->getWechatRecode(['wid' => $wid, 'uid' => $uid]);
                    $recode2 = $Recode->getRecodeWithAstro(['id' => $rid]);

                    if ($recode1 && $recode2) {
                        //将档案2日月升转换为文字
                        $sun2 = $this->recode_astro($recode2['sun']);
                        $moon2 = $this->recode_astro($recode2['moon']);
                        $asc2 = $this->recode_astro($recode2['asc']);

                        $arr = [
                            'wid1' => $wid,
                            'rid2' => $rid,
                            'isself1' => false,
                            'isself2' => false,
                            'sun_moon_asc1' => $recode1['sun_moon_asc'],
                            'sun_moon_asc2' => '日' . $sun2 . '月' . $moon2 . '升' . $asc2,
                            'name1' => $recode1['name'],
                            'name2' => $recode2['name'],
                            'avatar1' => $recode1['avatar'],
                            'avatar2' => $recode2['avatar']
                        ];

                        if ($recode2['isself'] == 1) {
                            $arr['isself2'] = true;
                        }
                    }
                }
            } elseif ($wid1 && $wid2) {
                //获取鉴爱的结果id
                $data['result1'] = $dd['result1'];
                //获取鉴爱的档案信息
                $recode1 = $WechatRecode->getWechatRecode(['wid' => $wid1, 'uid' => $uid]);
                $recode2 = $WechatRecode->getWechatRecode(['wid' => $wid2, 'uid' => $uid]);

                if ($recode1 && $recode2) {
                    $arr = [
                        'wid1' => $wid1,
                        'wid2' => $wid2,
                        'isself1' => false,
                        'isself2' => false,
                        'sun_moon_asc1' => $recode1['sun_moon_asc'],
                        'sun_moon_asc2' => $recode2['sun_moon_asc'],
                        'name1' => $recode1['name'],
                        'name2' => $recode2['name'],
                        'avatar1' => $recode1['avatar'],
                        'avatar2' => $recode2['avatar']
                    ];
                }
            }

            if ($data && $arr && $recode1 && $recode2) {
                $AuthenticateLoveText = new AuthenticateLoveText();
                //获取鉴爱的结果内容
                $result1 = $AuthenticateLoveText->getAuthenticateText(['result' => $data['result1']]);
                if (!empty($result1['tags'])) {
                    $arr['tags'] = array_slice($result1['tags'], 0, 3);
                } else {
                    $arr['tags'] = ['迷之缘分'];
                }

            }
            if ($arr)
                $recc[] = $arr;
        }
        return $recc;
    }

    /**
     * 获取两个档案的鉴爱结果
     * @param array $map
     * @return array
     * @throws \app\common\lib\exception\ApiException
     */
    public function getAuthenticateResult($map = [])
    {
        $rid1 = intval($map['rid1']) ?? 0;
        $wid1 = intval($map['wid1']) ?? 0;
        $rid2 = intval($map['rid2']) ?? 0;
        $wid2 = intval($map['wid2']) ?? 0;
        $atype = $map['atype'] ?? 0;
        $is_save = $map['is_save'] ?? 0;

        $uid = intval($map['uid']);

        $arr = [];
        $arr['archives1_info']['isself'] = 0;
        $arr['archives2_info']['isself'] = 0;
        $data = false;

        //获取当前用户的自己的档案
        $Recode = new Recode();
        $self_id = $Recode->getSelfRecode(['uid' => $uid]);

        if ($rid1 && $rid2) {
            $type = 1;
            $cacheKey = $uid . '_authlove_t' . $type . '_' . $rid1 . '_' . $rid2;
            $field = ['rid1','rid2','result1','result2'];
            $where = "((rid1 = $rid1 and rid2 = $rid2) or (rid1 = $rid2 and rid2 = $rid1)) ";
        } elseif (($rid1 && $wid2) || ($wid1 && $rid2)) {
            $type = 2;
            $rid = $rid1 > 0 ? $rid1 : $rid2;
            $wid = $wid1 > 0 ? $wid1 : $wid2;

            $cacheKey = $uid . '_authlove_t' . $type . '_' . $rid . '_' . $wid;
            $field = ['rid1','rid2','wid1','wid2','result1','result2'];
            $where = "((rid1 = $rid and wid2 = $wid) or (rid2 = $rid and wid1 = $wid)) ";
        } elseif ($wid1 && $wid2) {
            $type = 3;
            $cacheKey = $uid . '_authlove_t' . $type . '_' . $wid1 . '_' . $wid2;
            $field = ['wid1','wid2','result1','result2'];
            $where = "((wid1 = $wid1 and wid2 = $wid2) or (wid1 = $wid2 and wid2 = $wid1)) ";
        } else {
            return [];
        }
        $where2 = ['uid' => $uid, 'status' => 0];

        // 获取档案信息
        // rid1 rid2
        if ($type == 1) {
            $recode1 = $Recode->getRecodeWithAstro(['id' => $rid1]);
            $recode2 = $Recode->getRecodeWithAstro(['id' => $rid2]);

            if ($recode1['id'] == $self_id['id']) {
                $arr['archives1_info']['isself'] = 1;
            } elseif ($recode2['id'] == $self_id) {
                $arr['archives2_info']['isself'] = 1;
            }

            //将档案1日月升转换为文字
            $sun1 = $this->recode_astro($recode1['sun']);
            $moon1 = $this->recode_astro($recode1['moon']);
            $asc1 = $this->recode_astro($recode1['asc']);
            //将档案2日月升转换为文字
            $sun2 = $this->recode_astro($recode2['sun']);
            $moon2 = $this->recode_astro($recode2['moon']);
            $asc2 = $this->recode_astro($recode2['asc']);

            $arr['archives1_info']['sun_moon_asc'] = '日' . $sun1 . '月' . $moon1 . '升' . $asc1;
            $arr['archives2_info']['sun_moon_asc'] = '日' . $sun2 . '月' . $moon2 . '升' . $asc2;

        }// wid1 wid2
        elseif ($type == 3) {
            $WechatRecode = new WechatRecode();
            $recode1 = $WechatRecode->getWechatRecode(['wid' => $wid1, 'uid' => $uid]);
            $recode2 = $WechatRecode->getWechatRecode(['wid' => $wid2, 'uid' => $uid]);

            $arr['archives1_info']['sun_moon_asc'] = $recode1['sun_moon_asc'];
            $arr['archives2_info']['sun_moon_asc'] = $recode2['sun_moon_asc'];

            $birth_time1 = strtotime($recode1['birth_time']);
            $recode1['year'] = date('Y', $birth_time1);
            $recode1['month'] = date('m', $birth_time1);
            $recode1['day'] = date('d', $birth_time1);
            $recode1['hour'] = date('H', $birth_time1);
            $recode1['minute'] = date('i', $birth_time1);
            $recode1['timezone'] = 8;
            $recode1['is_summer'] = isSummerTime($recode1['hour'], $recode1['minute'], 0, $recode1['month'], $recode1['day'], $recode1['year']) ? 1 : 0;


            $birth_time2 = strtotime($recode2['birth_time']);
            $recode2['year'] = date('Y', $birth_time2);
            $recode2['month'] = date('m', $birth_time2);
            $recode2['day'] = date('d', $birth_time2);
            $recode2['hour'] = date('H', $birth_time2);
            $recode2['minute'] = date('i', $birth_time2);
            $recode2['timezone'] = 8;
            $recode2['is_summer'] = isSummerTime($recode2['hour'], $recode2['minute'], 0, $recode2['month'], $recode2['day'], $recode2['year']) ? 1 : 0;

        } else {
            $WechatRecode = new WechatRecode();
            if ($rid1 !== 0) {
                $recode1 = $Recode->getRecodeWithAstro(['id' => $rid1]);

                if ($recode1['id'] == $self_id['id']) {
                    $arr['archives1_info']['isself'] = 1;
                }

                //将档案2日月升转换为文字
                $sun = $this->recode_astro($recode1['sun']);
                $moon = $this->recode_astro($recode1['moon']);
                $asc = $this->recode_astro($recode1['asc']);

                $arr['archives1_info']['sun_moon_asc'] = '日' . $sun . '月' . $moon . '升' . $asc;

            } else {
                $recode1 = $WechatRecode->getWechatRecode(['wid' => $wid1, 'uid' => $uid]);

                $arr['archives1_info']['sun_moon_asc'] = $recode1['sun_moon_asc'];

                $birth_time = strtotime($recode1['birth_time']);
                $recode1['year'] = date('Y', $birth_time);
                $recode1['month'] = date('m', $birth_time);
                $recode1['day'] = date('d', $birth_time);
                $recode1['hour'] = date('H', $birth_time);
                $recode1['minute'] = date('i', $birth_time);
                $recode1['timezone'] = 8;
                $recode1['is_summer'] = isSummerTime($recode1['hour'], $recode1['minute'], '00', $recode1['month'], $recode1['day'], $recode1['year']) ? 1 : 0;
            }
            if ($rid2 !== 0) {
                $recode2 = $Recode->getRecodeWithAstro(['id' => $rid2]);

                if ($recode2['id'] == $self_id['id']) {
                    $arr['archives2_info']['isself'] = 1;
                }

                //将档案2日月升转换为文字
                $sun = $this->recode_astro($recode2['sun']);
                $moon = $this->recode_astro($recode2['moon']);
                $asc = $this->recode_astro($recode2['asc']);

                $arr['archives2_info']['sun_moon_asc'] = '日' . $sun . '月' . $moon . '升' . $asc;

            } else {
                $recode2 = $WechatRecode->getWechatRecode(['wid' => $wid2, 'uid' => $uid]);

                $arr['archives2_info']['sun_moon_asc'] = $recode2['sun_moon_asc'];

                $birth_time = strtotime($recode2['birth_time']);
                $recode2['year'] = date('Y', $birth_time);
                $recode2['month'] = date('m', $birth_time);
                $recode2['day'] = date('d', $birth_time);
                $recode2['hour'] = date('H', $birth_time);
                $recode2['minute'] = date('i', $birth_time);
                $recode2['timezone'] = 8;
                $recode2['is_summer'] = isSummerTime($recode2['hour'], $recode2['minute'], 0, $recode2['month'], $recode2['day'], $recode2['year']) ? 1 : 0;
            }
        }

        if ($recode1 && $recode2)
        {

            // 缓存开启，从缓存获取数据
            if ($this->cache_on >= 1) {
                $data = Cache::get($cacheKey);
            }
            //非實時計算並且缓存数据为空，从数据库取
            if ($this->resultAlwaysCalculate === false && $data === false) {
                try {
                    $data = $this->select($field)->where($where)->where($where2)->findOrFail();
                    $data = json_decode(json_encode($data, true), true);
                } catch (\Exception $e) {
                    $data = [];
                }

                // 缓存开启，写入缓存
                if (!empty($data) && $this->cache_on >= 1) {
                    Cache::set($cacheKey, $data, self::CACHE_TIME);

                    //删除鉴爱历史记录缓存
                    Cache::forget('authenticate_history_' . $uid);
                }
            }

            // 计算鉴爱结果
            // 若是实时计算删除历史纪录，重新加入数据库
            if ($this->resultAlwaysCalculate === true || ($data === false || empty($data))) {
                $result = $this->caclAuthenticateResult($uid, $rid1, $rid2, $wid1, $wid2, $recode1, $recode2, $atype);

                $data = [
                    'uid' => $uid,
                    'rid1' => $rid1,
                    'rid2' => $rid2,
                    'wid1' => $wid1,
                    'wid2' => $wid2,
                    'result1' => $result['result1'],
                    'result2' => $result['result2'],
                    'create_time' => time()
                ];

                try {
                    $this->where($where)->delete();
                    $this->insert($data);
                    Cache::forget($cacheKey);
                } catch (\Exception $e) {
                    \Log::info($where . PHP_EOL . $e->getMessage());
                    throw new ApiException($e->getMessage(), 200, config('code.error'));
                }

                // 缓存开启，写入缓存
                if ($this->cache_on >= 1) {
                    Cache::set($cacheKey, $data, self::CACHE_TIME);
                    //删除鉴爱历史记录缓存
                    Cache::forget('authenticate_history_' . $uid);
                }
            }
            //\think\Log::write('type:' . $type.PHP_EOL ,'log',true);
            //\think\Log::write("rid1:{$rid1}  rid2:{$rid2}  wid1:{$wid1}  wid2:{$wid2}" . PHP_EOL,'log',true);
            //\think\Log::write("rid1:{$data['rid1']}  rid2:{$data['rid2']}  wid1:{$data['wid1']}  wid2:{$data['wid2']}" . PHP_EOL,'log',true);
            // [ log ] type:2
            // [ log ] rid1:0  rid2:8  wid1:46  wid2:0
            // [ log ] rid1:8  rid2:0  wid1:0  wid2:46
            // 判断是否需要交换结果顺序  A_VS_B  || B_VS_A
            if (
                ($type === 1 && $rid1 != intval($data['rid1']))
                || ($type === 2 && $rid2 !== 0 && $rid2 === intval($data['rid1']))
                || ($type === 3 && $wid1 != intval($data['wid1']))
            ) {
                $temp = $data['result1'];
                $data['result1'] = $data['result2'];
                $data['result2'] = $temp;
            }
            $AuthenticateLoveText = new AuthenticateLoveText();
            //获取鉴爱的结果内容
            $result1 = $AuthenticateLoveText->getAuthenticateText(['result' => $data['result1'], 'recode1' => $recode1, 'recode2' => $recode2, 'self_id' => $self_id, 'is_save' => $is_save]);
//        //若当前结果为空，默认为迷之缘分
//        if (!$result1['text'])
//        {
//            $result1 = $AuthenticateLoveText->getAuthenticateText(['result' => '22-100', 'recode1' => $recode1, 'recode2' => $recode2, 'self_id' => $self_id]);
//        }
            $result2 = $AuthenticateLoveText->getAuthenticateText(['result' => $data['result2'], 'recode1' => $recode2, 'recode2' => $recode1, 'self_id' => $self_id, 'is_save' => $is_save]);
            //若当前结果为空，默认为迷之缘分
//        if (!$result2['text'])
//        {
//            $result2 = $AuthenticateLoveText->getAuthenticateText(['result' => '22-100', 'recode1' => $recode2, 'recode2' => $recode1, 'self_id' => $self_id]);
//        }
            if ($result1 && $result2) {
                $arr['result_list1'] = $result1['text'];
                $arr['result_list2'] = $result2['text'];
                $arr['archives1_info']['avatar'] = $recode1['avatar'];
                $arr['archives1_info']['name'] = $recode1['name'];
                $arr['archives2_info']['avatar'] = $recode2['avatar'];
                $arr['archives2_info']['name'] = $recode2['name'];

            }
        }


        return $arr;
    }

    /**
     * 判断档案的日月升信息
     * @param $astro
     * @return string
     */
    public function recode_astro($astro)
    {
        $astro = explode('-', $astro)[0];
        // 获取星座名称配置
        $sign_name = config('astrolog.sign_name');
        //
        $sign = intval($astro);

        $info = explode('|', $sign_name[$sign])[2] ?? '';

        return $info;
    }

    /**
     * 计算鉴爱结果
     * @param $uid
     * @param int $rid1
     * @param int $rid2
     * @param int $wid1
     * @param int $wid2
     * @param array $recode1
     * @param array $recode2
     * @param int $atype
     * @return array
     * @throws ApiException
     */
    protected function caclAuthenticateResult($uid, $rid1 = 0, $rid2 = 0, $wid1 = 0, $wid2 = 0, $recode1 = [], $recode2 = [], $atype = 0)
    {
        $Astrolog = Astrolog::getInstance();

        $sourceData1 = $Astrolog
            ->setRecode1($recode1)
            ->setRecode2($recode2)
            ->setExecPrefix(config('astrolog.prefix'))
            ->setIsAstrolabe(false)
            ->setUserSetting(config('astroset.setting1'))
            ->setGetDatas(['synastry','natal'])
            ->getAstroDatas();


        $synastryData1 = $sourceData1->getDatas('synastry');
        $natalData1 = $sourceData1->getDatas('natal');
        // 本命盘行星结构数据
        $natalData1 = $Astrolog->get_structure($natalData1, true);

        $sourceData2 = $Astrolog
            ->setRecode1($recode1)
            ->setRecode2($recode2)
            ->getAstroDatas();


        $synastryData2 = $sourceData2->getDatas('synastry');
        $natalData2 = $sourceData2->getDatas('natal');
        // 本命盘行星结构数据
        $natalData2 = $Astrolog->get_structure($natalData2, true);


        $Synastry = new Synastry([
            'recode1' => $recode1,
            'recode2' => $recode2,
            // A为底盘 对方落我宫与我成相
            'data1' => $synastryData1,
            // B为底盘 对方落我宫与我成相
            'data2' =>$synastryData2,
        ]);
        // 获取合盘指数
        $Synastry->init();
        // 本命盘行星结构数据


        $AuthenticateLove = new AuthenticateLove([
            'recode1' => $recode1,
            'recode2' => $recode2,
            // A为底盘 对方落我宫与我成相
            'data1' => $synastryData1,
            'natal_data1' => $natalData1,
            // B为底盘 对方落我宫与我成相
            'data2' => $synastryData2,
            'natal_data2' => $natalData2,
            // 合盘指数
            'synastryScore' => $Synastry->data['score'],
            // 和谐冲突度 0=>和谐,1=>冲突
            'harmoniousConflict' => $Synastry->data['harmoniousConflict'],
        ]);

        $result = $AuthenticateLove->init();

        //若计算成功且atype=1（h5计算），发送消息
        if ($result && $atype) {
            //获取消息跳转连接
            if ($rid1 && $rid2) {
                $link = 'identify_result?rid1=' . $recode1['id'] . '&rid2=' . $recode2['id'] . '&wid1=0&wid2=0';
            } elseif ($wid1 && $rid2) {
                $link = 'identify_result?rid1=0&rid2=' . $recode2['id'] . '&wid1=' . $recode1['id'] . '&wid2=0';
            } elseif ($rid1 && $wid2) {
                $link = 'identify_result?rid1=' . $recode1['id'] . '&rid2=0&wid1=0&wid2=' . $recode2['id'];
            } elseif ($wid1 && $wid2) {
                $link = 'identify_result?rid1=0&rid2=0wid1=' . $recode1['id'] . '&wid2=' . $recode2['id'];
            } else {
                $link = '';
            }
            $content = $recode1['name'] . '和' . $recode2['name'] . '的鉴爱已有结果，请查看。';
            MessageCenter::pushMessage(['uid'=>$uid,'title'=>'鉴爱结果完成','content'=>$content,'link'=>$link,'target'=>'local']);
        }

        return $result;
    }
}
